#include "../include/Socket.h"
#include "../include/Common.h"
#include <iostream>
#include <string>
#include <thread>
#include <signal.h>
#include "../Http/Http.hpp"

void read_thread_func(Socket *sock)
{
    char buf[1024];
    while (true)
    {
        ssize_t recv_bytes = sock->Recv(buf, sizeof(buf) - 1);
        if (recv_bytes > 0)
        {
            buf[recv_bytes] = '\0';
            std::cout << "\rReceived: " << buf << std::endl
                      << "> " << std::flush;
        }
        else if (recv_bytes == 0)
        {
            std::cout << "\rServer closed the connection." << std::endl;
            exit(0);
        }
        else
        {
            std::cout << "\rReceive failed. Exiting." << std::endl;
            exit(1);
        }
    }
}
void testLongLink()
{
    Socket cli_sock;
    cli_sock.CreateClientConn(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    while (true)
    {
        cli_sock.Send(&req[0], req.size());
        // assert(cli_sock.Send(&req[0], req.size()) != -1);
        char buf[1024];
        cli_sock.Recv(buf, 1023);
        // assert(cli_sock.Recv(buf, 1023));
        DBG_LOG("[%s]", buf);
        sleep(10);
    }
    cli_sock.Close();
}
void testInactiveLink()
{
    Socket cli_sock;
    cli_sock.CreateClientConn(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    while (true)
    {
        cli_sock.Send(&req[0], req.size());
        char buf[1024];
        cli_sock.Recv(buf, 1023);
        DBG_LOG("[%s]", buf);
        sleep(10);
    }
    cli_sock.Close();
}

void testErrorRequest()
{

    Socket cli_sock;
    cli_sock.CreateClientConn(8080, "127.0.0.1");
    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 100\r\n\r\n";
    while (true)
    {
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        char buf[1024];
        cli_sock.Recv(buf, 1023);
        DBG_LOG("[%s]", buf);
        sleep(10);
    }
    cli_sock.Close();
}

// 处理一个业务花费了太长时间，超过了服务器设置的非活跃连接超时时间
// 导致其他的连接也被拖累超时，导致被动释放
int testTimeout()
{
    signal(SIGCHLD, SIG_IGN);
    for (int i = 0; i < 10; i++)
    {
        pid_t pid = fork();
        if (pid < 0)
        {
            DBG_LOG("FORK ERROR");
            return -1;
        }
        else if (pid == 0)
        {
            Socket cli_sock;
            cli_sock.CreateClientConn(8080, "127.0.0.1");
            std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
            while (true)
            {
                assert(cli_sock.Send(&req[0], req.size()) != -1);
                char buf[1024];
                assert(cli_sock.Recv(buf, 1023));
                DBG_LOG("[%s]", buf);
                sleep(15);
            }
            cli_sock.Close();
            exit(0);
        }
    }
    while (true)
        sleep(1);
}
void testMultiRequest()
{
    Socket cli_sock;
    cli_sock.CreateClientConn(8080, "127.0.0.1");

    std::string req = "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    req += "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    req += "GET /hello HTTP/1.1\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
    while (1)
    {
        assert(cli_sock.Send(&req[0], req.size()) != -1);
        char buf[1024] = {0};
        assert(cli_sock.Recv(buf, 1023));
        DBG_LOG("[%s]", buf);
        sleep(3);
    }
    cli_sock.Close();
}
void testBigFileDelive()
{
    Socket cli_sock;
    cli_sock.CreateClientConn(8080, "127.0.0.1");
    std::string req = "PUT /1234.txt HTTP/1.1\r\nConnection: keep-alive\r\n";
    std::string body;
    Util::ReadFile("/home/wk/Code/project-c/HighConcurrencyServer/test/hello.txt", body);
    req += "Content-Length: " + std::to_string(body.size()) + "\r\n\r\n";
    assert(cli_sock.Send(req.c_str(), req.size()) != -1);
    assert(cli_sock.Send(body.c_str(), body.size()) != -1);
    char buf[1024] = {0};
    assert(cli_sock.Recv(buf, 1023));
    DBG_LOG("[%s]", buf);
    sleep(3);
    cli_sock.Close();
}
int main()
{
    // Socket cli_sock;
    // if (!cli_sock.CreateClientConn(8500, "127.0.0.1"))
    // {
    //     ERR_LOG("Failed to connect to server");
    //     return 1;
    // }

    // std::cout << "Successfully connected to server. Type messages and press Enter to send." << std::endl;

    // std::thread(read_thread_func, &cli_sock).detach();

    // std::string line;
    // while (true)
    // {
    //     std::cout << "> " << std::flush;
    //     if (!std::getline(std::cin, line))
    //     {
    //         // Ctrl+D or other EOF
    //         break;
    //     }

    //     if (line.empty())
    //     {
    //         continue;
    //     }

    //     if (cli_sock.Send((void *)line.c_str(), line.size()) < 0)
    //     {
    //         ERR_LOG("Send failed");
    //         break;
    //     }
    // }

    // std::cout << "Client shutting down." << std::endl;
    // cli_sock.Close();
    // testLongLink();
    // testInactiveLink();
    // testErrorRequest();
    // testTimeout();
    // testMultiRequest();
    testBigFileDelive();
    return 0;
}
